package org.sqltomongo.executor;

import cn.org.wangchangjiu.sqltomongo.core.common.MongoParserResult;
import cn.org.wangchangjiu.sqltomongo.core.parser.SelectSQLTypeParser;
import cn.org.wangchangjiu.sqltomongo.core.parser.data.PartSQLParserData;
import cn.org.wangchangjiu.sqltomongo.core.util.SqlCommonUtil;
import cn.org.wangchangjiu.sqltomongo.core.util.SqlSupportedSyntaxCheckUtil;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.sqltomongo.cache.Cache;
import org.sqltomongo.orm.Configuration;
import org.sqltomongo.util.SqlParameterSetterUtil;

import java.util.List;

/**
 * @Classname DefaultExecutor
 * @Description
 * @Date 2022/8/9 16:57
 * @Created by wangchangjiu
 */
public class DefaultExecutor implements Executor {

    private MongoTemplate mongoTemplate;

    private SelectSQLTypeParser selectSQLTypeParser;

    private Configuration configuration;

    public DefaultExecutor(MongoTemplate mongoTemplate, SelectSQLTypeParser selectSQLTypeParser, Configuration configuration){
        this.mongoTemplate = mongoTemplate;
        this.selectSQLTypeParser = selectSQLTypeParser;
        this.configuration = configuration;
    }

    @Override
    public PartSQLParserData sqlParserData(String originalSql, Object... parameters){
        // 检查 SQL 是否是 SELECT 语句
        SqlSupportedSyntaxCheckUtil.checkSqlType(originalSql, SqlCommonUtil.SqlType.SELECT);

        Cache cache = configuration.getParserCache().getCache();
        PartSQLParserData parserData = (PartSQLParserData) cache.getObject(cache.generateCacheKey(originalSql));
        if(parserData != null){
            return parserData;
        }
        // 设置参数
        String parameterSql = SqlParameterSetterUtil.parameterSetter(originalSql, parameters);
        // 获取解析数据
        PartSQLParserData data = selectSQLTypeParser.getPartSQLParserData(parameterSql);
        // 设置缓存
        cache.putObject(cache.generateCacheKey(originalSql), data);
        return data;
    }


    @Override
    public <T> T selectOne(Class<T> returnType, PartSQLParserData data){
        MongoParserResult result = selectSQLTypeParser.mongoAggregationAnalyzer(data);
        // 使用 MongoTemplate 的 aggregate 聚合查询 API 获取结果
        List<T> list = mongoTemplate.executeCommand(result.formatCommand())
                .get("cursor", Document.class).getList("firstBatch", returnType);
        return list.get(0);
    }

    @Override
    public <T> T selectOne(String sql, Class<T> returnType, Object... parameters) {
        PartSQLParserData data = this.sqlParserData(sql, parameters);
        // 解析 SQL 并返回封装 Mongo 的API
       return this.selectOne(returnType, data);
    }

    @Override
    public <T> List<T> selectList(String originalSql, Class<T> returnType, Object... parameters) {
        SqlSupportedSyntaxCheckUtil.checkSqlType(originalSql, SqlCommonUtil.SqlType.SELECT);
        Cache cache = configuration.getParserCache().getCache();
        PartSQLParserData parserData;
        if(!cache.existObject(cache.generateCacheKey(originalSql))){
            String parameterSql =  SqlParameterSetterUtil.parameterSetter(originalSql, parameters);
            // 解析后的数据
            parserData = selectSQLTypeParser.getPartSQLParserData(parameterSql);
        } else {
            parserData = (PartSQLParserData) cache.getObject(cache.generateCacheKey(originalSql));
        }
        MongoParserResult result = selectSQLTypeParser.mongoAggregationAnalyzer(parserData);
        List<T> list = mongoTemplate.executeCommand(result.formatCommand())
                .get("cursor", Document.class).getList("firstBatch", returnType);
        return list;
    }

    @Override
    public <T> List<T> selectList(Class<T> returnType, PartSQLParserData data) {
        MongoParserResult result = selectSQLTypeParser.mongoAggregationAnalyzer(data);
        // 使用 MongoTemplate 的 aggregate 聚合查询 API 获取结果
        List<T> list = mongoTemplate.executeCommand(result.formatCommand())
                .get("cursor", Document.class).getList("firstBatch", returnType);
        return list;
    }
}
